﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;

namespace RiskMan.DataClass.Models.Plaza_II.FortsFuttradeRepl
{
    /// <summary>
    /// Журнал сделок
    /// Поля code_sell, comment_sell, ext_id_sell, trust_sell, hedge_sell, login_sell, code_rts_sell, fee_sell, code_buy
    /// comment_buy, ext_id_buy, trust_buy, hedge_buy, login_buy, code_rts_buy, fee_buy, заполняются только для
    /// своих сделок
    /// </summary>
    public class Deal : INotifyPropertyChanged
    {
        #region private

        private long _replId;
        private long _replRev;
        private long _replAct;
        private long _idDeal;
        private int _sessId;
        private int _isinId;
        private Decimal _price;
        private int _amount;
        private DateTime _moment;
        private string _codeSell;
        private string _codeBuy;
        private long _idOrdSell;
        private int _extIdSell;
        private string _commentSell;
        private int _trustSell;
        private int _statusSell;
        private long _idOrdBuy;
        private int _extIdBuy;
        private string _commentBuy;
        private int _trustBuy;
        private int _statusBuy;
        private int _pos;
        private int _nosystem;
        private long _idRepo;
        private int _hedgeSell;
        private int _hedgeBuy;
        private Decimal _feeSell;
        private Decimal _feeBuy;
        private string _loginSell;
        private string _loginBuy;
        private string _codeRtsSell;
        private string _codeRtsBuy;
        private long _idDealMultileg;

        #endregion

        #region public

        /// <summary>
        /// Служебное поле подсистемы репликации
        /// </summary>
        public long ReplId
        {
            get { return _replId; }
            set
            {
                if (_replId != value)
                {
                    _replId = value;
                    RaisePropertyChanged("ReplId");
                }
            }
        }

        /// <summary>
        /// Служебное поле подсистемы репликации
        /// </summary>
        public long ReplRev
        {
            get { return _replRev; }
            set
            {
                if (_replRev != value)
                {
                    _replRev = value;
                    RaisePropertyChanged("ReplRev");
                }
            }
        }

        /// <summary>
        /// Служебное поле подсистемы репликации
        /// </summary>
        public long ReplAct
        {
            get { return _replAct; }
            set
            {
                if (_replAct != value)
                {
                    _replAct = value;
                    RaisePropertyChanged("ReplAct");
                }
            }
        }

        /// <summary>
        /// Номер сделки
        /// </summary>
        public long IdDeal
        {
            get { return _idDeal; }
            set
            {
                if (_idDeal != value)
                {
                    _idDeal = value;
                    RaisePropertyChanged("IdDeal");
                }
            }
        }

        /// <summary>
        /// Идентификатор торговой сессии
        /// </summary>
        public int SessId
        {
            get { return _sessId; }
            set
            {
                if (_sessId != value)
                {
                    _sessId = value;
                    RaisePropertyChanged("SessId");
                }
            }
        }

        /// <summary>
        /// Уникальный числовой идентификатор инструмента
        /// </summary>
        public int IsinId
        {
            get { return _isinId; }
            set
            {
                if (_isinId != value)
                {
                    _isinId = value;
                    RaisePropertyChanged("IsinId");
                }
            }
        }

        /// <summary>
        /// Цена
        /// </summary>
        public Decimal Price
        {
            get { return _price; }
            set
            {
                if (_price != value)
                {
                    _price = value;
                    RaisePropertyChanged("Price");
                }
            }
        }

        /// <summary>
        /// Объем, кол-во единиц инструмента
        /// </summary>
        public int Amount
        {
            get { return _amount; }
            set
            {
                if (_amount != value)
                {
                    _amount = value;
                    RaisePropertyChanged("Amount");
                }
            }
        }

        /// <summary>
        /// Время заключения сделки
        /// </summary>
        public DateTime Moment
        {
            get { return _moment; }
            set
            {
                if (_moment != value)
                {
                    _moment = value;
                    RaisePropertyChanged("Moment");
                }
            }
        }

        /// <summary>
        /// Код продавца
        /// </summary>
        public string CodeSell
        {
            get { return _codeSell; }
            set
            {
                if (_codeSell != value)
                {
                    _codeSell = value;
                    RaisePropertyChanged("CodeSell");
                }
            }
        }

        /// <summary>
        /// Код покупателя
        /// </summary>
        public string CodeBuy
        {
            get { return _codeBuy; }
            set
            {
                if (_codeBuy != value)
                {
                    _codeBuy = value;
                    RaisePropertyChanged("CodeBuy");
                }
            }
        }

        /// <summary>
        /// Номер заявки продавца
        /// </summary>
        public long IdOrdSell
        {
            get { return _idOrdSell; }
            set
            {
                if (_idOrdSell != value)
                {
                    _idOrdSell = value;
                    RaisePropertyChanged("IdOrdSell");
                }
            }
        }

        /// <summary>
        /// Внешний номер из заявки продавца
        /// </summary>
        public int ExtIdSell
        {
            get { return _extIdSell; }
            set
            {
                if (_extIdSell != value)
                {
                    _extIdSell = value;
                    RaisePropertyChanged("ExtIdSell");
                }
            }
        }

        /// <summary>
        /// Комментарий из заявки продавца
        /// </summary>
        public string CmmentSell
        {
            get { return _commentSell; }
            set
            {
                if (_commentSell != value)
                {
                    _commentSell = value;
                    RaisePropertyChanged("CmmentSell");
                }
            }
        }

        /// <summary>
        /// Признак ДУ (доверительного управления) из заявки продавца
        /// </summary>
        public int TrustSell
        {
            get { return _trustSell; }
            set
            {
                if (_trustSell != value)
                {
                    _trustSell = value;
                    RaisePropertyChanged("TrustSell");
                }
            }
        }

        /// <summary>
        /// Статус сделки со стороны продавца
        /// Поля status_sell и status_buy являются битовыми масками, определяющими следующие значения:
        /// 0x20 Сделка является сделкой экспирации
        /// 0x80 Признак истечения времени действия инструмента
        /// 0x8000 Сделка T+0 по переносу позиции
        /// 0x20000 Техническая сделка (Репо)
        /// 0x40000 Техническая сделка (Связанная парная заявка)
        /// 0x1000000 Сделка поставки через RTS Standard
        /// 0x2000000 Сделка сформированная вне торгов
        /// 0x4000000 Адресная сделка
        /// 0x8000000 Сделка по связке
        /// 0x10000000 Сделка при непоставке
        /// 0x40000000 Сделка исполнения фьючерса или инструмента RTS Standard (кроме исполнения фьючерса через RTS Standard)
        /// 
        /// Для "чужих" сделок в полях status_buy и status_sell могут заполняються биты 0x4, 0x2000000, 0x4000000
        /// и 0x8000000
        /// </summary>
        public int StatusSell
        {
            get { return _statusSell; }
            set
            {
                if (_statusSell != value)
                {
                    _statusSell = value;
                    RaisePropertyChanged("StatusSell");
                }
            }
        }

        /// <summary>
        /// Номер заявки покупателя
        /// </summary>
        public long IdOrdBuy
        {
            get { return _idOrdBuy; }
            set
            {
                if (_idOrdBuy != value)
                {
                    _idOrdBuy = value;
                    RaisePropertyChanged("IdOrdBuy");
                }
            }
        }

        /// <summary>
        /// Внешний номер из заявки покупателя
        /// </summary>
        public int ExtIdBuy
        {
            get { return _extIdBuy; }
            set
            {
                if (_extIdBuy != value)
                {
                    _extIdBuy = value;
                    RaisePropertyChanged("ExtIdBuy");
                }
            }
        }

        /// <summary>
        /// Комментарий из заявки покупателя
        /// </summary>
        public string CommentBuy
        {
            get { return _commentBuy; }
            set
            {
                if (_commentBuy != value)
                {
                    _commentBuy = value;
                    RaisePropertyChanged("CommentBuy");
                }
            }
        }

        /// <summary>
        /// Признак ДУ (доверительного управления) из заявки покупателя
        /// </summary>
        public int TrustBuy
        {
            get { return _trustBuy; }
            set
            {
                if (_trustBuy != value)
                {
                    _trustBuy = value;
                    RaisePropertyChanged("TrustBuy");
                }
            }
        }

        /// <summary>
        /// Статус сделки со стороны покупателя
        /// Поля status_sell и status_buy являются битовыми масками, определяющими следующие значения:
        /// 0x20 Сделка является сделкой экспирации
        /// 0x80 Признак истечения времени действия инструмента
        /// 0x8000 Сделка T+0 по переносу позиции
        /// 0x20000 Техническая сделка (Репо)
        /// 0x40000 Техническая сделка (Связанная парная заявка)
        /// 0x1000000 Сделка поставки через RTS Standard
        /// 0x2000000 Сделка сформированная вне торгов
        /// 0x4000000 Адресная сделка
        /// 0x8000000 Сделка по связке
        /// 0x10000000 Сделка при непоставке
        /// 0x40000000 Сделка исполнения фьючерса или инструмента RTS Standard (кроме исполнения фьючерса через RTS Standard)
        ///          
        /// Для "чужих" сделок в полях status_buy и status_sell могут заполняються биты 0x4, 0x2000000, 0x4000000
        /// и 0x8000000
        /// </summary>
        public int StatusBuy
        {
            get { return _statusBuy; }
            set
            {
                if (_statusBuy != value)
                {
                    _statusBuy = value;
                    RaisePropertyChanged("StatusBuy");
                }
            }
        }

        /// <summary>
        /// Кол-во позиций по инструменту на рынке после сделки
        /// </summary>
        public int Pos
        {
            get { return _pos; }
            set
            {
                if (_pos != value)
                {
                    _pos = value;
                    RaisePropertyChanged("Pos");
                }
            }
        }

        /// <summary>
        /// Признак внесистемной сделки
        /// </summary>
        public int Nosystem
        {
            get { return _nosystem; }
            set
            {
                if (_nosystem != value)
                {
                    _nosystem = value;
                    RaisePropertyChanged("Nosystem");
                }
            }
        }

        /// <summary>
        /// Номер другой части сделки РЕПО
        /// Поле id_repo содержит номер другой части сделки РЕПО. Для I-й части поле содержит номер II-й части,
        ///для II-й части – номер I-й
        /// </summary>
        public long IdRepo
        {
            get { return _idRepo; }
            set
            {
                if (_idRepo != value)
                {
                    _idRepo = value;
                    RaisePropertyChanged("IdRepo");
                }
            }
        }

        /// <summary>
        /// Признак хеджевой сделки со стороны продавца
        /// </summary>
        public int HedgeSell
        {
            get { return _hedgeSell; }
            set
            {
                if (_hedgeSell != value)
                {
                    _hedgeSell = value;
                    RaisePropertyChanged("HedgeSell");
                }
            }
        }

        /// <summary>
        /// Признак хеджевой сделки со стороны покупателя
        /// </summary>
        public int HedgeBuy
        {
            get { return _hedgeBuy; }
            set
            {
                if (_hedgeBuy != value)
                {
                    _hedgeBuy = value;
                    RaisePropertyChanged("HedgeBuy");
                }
            }
        }

        /// <summary>
        /// Сбор по сделке продавца
        /// </summary>
        public Decimal FeeSell
        {
            get { return _feeSell; }
            set
            {
                if (_feeSell != value)
                {
                    _feeSell = value;
                    RaisePropertyChanged("FeeSell");
                }
            }
        }

        /// <summary>
        /// Сбор по сделке покупателя
        /// </summary>
        public Decimal FeeBuy
        {
            get { return _feeBuy; }
            set
            {
                if (_feeBuy != value)
                {
                    _feeBuy = value;
                    RaisePropertyChanged("FeeBuy");
                }
            }
        }

        /// <summary>
        /// Логин пользователя продавца
        /// </summary>
        public string LoginSell
        {
            get { return _loginSell; }
            set
            {
                if (_loginSell != value)
                {
                    _loginSell = value;
                    RaisePropertyChanged("LoginSell");
                }
            }
        }

        /// <summary>
        /// Логин пользователя покупателя
        /// </summary>
        public string LoginBuy
        {
            get { return _loginBuy; }
            set
            {
                if (_loginBuy != value)
                {
                    _loginBuy = value;
                    RaisePropertyChanged("LoginBuy");
                }
            }
        }

        /// <summary>
        /// Код РТС продавца
        /// </summary>
        public string CodeRtsSell
        {
            get { return _codeRtsSell; }
            set
            {
                if (_codeRtsSell != value)
                {
                    _codeRtsSell = value;
                    RaisePropertyChanged("CodeRtsSell");
                }
            }
        }

        /// <summary>
        /// Код РТС покупателя
        /// </summary>
        public string CodeRtsBuy
        {
            get { return _codeRtsBuy; }
            set
            {
                if (_codeRtsBuy != value)
                {
                    _codeRtsBuy = value;
                    RaisePropertyChanged("CodeRtsBuy");
                }
            }
        }

        /// <summary>
        /// Номер сделки по связке
        /// Для технических сделок, являющимися результатами сделок по инструментам-связкам, поле nosystem
        ///всегда установлено в 1, вне зависимости от того, является ли сделка по связке системной или адресной.
        ///Для определения системности исходной сделки надо использовать признак nosystem соответствующей
        ///записи таблицы multileg_deal.
        /// Поле id_deal_multileg содержит код сделки по инструменту-связке, в случае если данная запись является
        ///записью о технической сделке. В случае сделки по обычному инструменту данное поле содержит 0.
        /// </summary>
        public long IdDealMultileg
        {
            get { return _idDealMultileg; }
            set
            {
                if (_idDealMultileg != value)
                {
                    _idDealMultileg = value;
                    RaisePropertyChanged("IdDealMultileg");
                }
            }
        }

        #endregion

        #region event PropertyChangedEventHandler

        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region processing
        public static Deal ParseDeal(Dictionary<String, String> relation)
        {
            Deal tmp = new Deal();
            tmp.Parse(relation);
            return tmp;
        }

        public void Parse(Dictionary<String, String> relation)
        {
            foreach (String field in relation.Keys)
            {
                String value = relation[field];

                switch (field)
                {
                    case "replID": long.TryParse(value, out _replId); break;
                    case "replRev": long.TryParse(value, out _replRev); break;
                    case "replAct": long.TryParse(value, out _replAct); break;
                    case "id_deal": long.TryParse(value, out _idDeal); break;
                    case "sess_id": int.TryParse(value, out _sessId); break;
                    case "isin_id": int.TryParse(value, out _isinId); break;
                    case "price": Decimal.TryParse(value, NumberStyles.Number, CultureInfo.GetCultureInfo("en-US"), out _price); break;
                    case "amount": int.TryParse(value, out _amount); break;
                    case "moment": DateTime.TryParse(value, out _moment); break;
                    case "code_sell": _codeSell = value; break;
                    case "code_buy": _codeBuy = value; break;
                    case "id_ord_sell": long.TryParse(value, out _idOrdSell); break;
                    case "ext_id_sell": int.TryParse(value, out _extIdSell); break;
                    case "comment_sell": _commentSell = value; break;
                    case "trust_sell": int.TryParse(value, out _trustSell); break;
                    case "status_sell": int.TryParse(value, out _statusSell); break;
                    case "id_ord_buy": long.TryParse(value, out _idOrdBuy); break;
                    case "ext_id_buy": int.TryParse(value, out _extIdBuy); break;
                    case "comment_buy": _commentBuy = value; break;
                    case "trust_buy": int.TryParse(value, out _trustBuy); break;
                    case "status_buy": int.TryParse(value, out _statusBuy); break;
                    case "pos": int.TryParse(value, out _pos); break;
                    case "nosystem": int.TryParse(value, out _nosystem); break;
                    case "id_repo": long.TryParse(value, out _idRepo); break;
                    case "hedge_sell": int.TryParse(value, out _hedgeSell); break;
                    case "hedge_buy": int.TryParse(value, out _hedgeBuy); break;
                    case "fee_sell": Decimal.TryParse(value, NumberStyles.Number, CultureInfo.GetCultureInfo("en-US"), out _feeSell); break;
                    case "fee_buy": Decimal.TryParse(value, NumberStyles.Number, CultureInfo.GetCultureInfo("en-US"), out _feeBuy); break;
                    case "login_sell": _loginSell = value; break;
                    case "login_buy": _loginBuy = value; break;
                    case "code_rts_sell": _codeRtsSell = value; break;
                    case "code_rts_buy": _codeRtsBuy = value; break;
                    case "id_deal_multileg": long.TryParse(value, out _idDealMultileg); break;

                };
            }
        }

        public static void AddValueToObsColDeal(Deal inst)
        {
            MainWindow.StaticLevel._dataProvider.DealList.Add(inst);
        }
        #endregion

    }
}
